"""
@Author：WangYuXiang
@E-mile：Hill@3io.cc
@CreateTime：2021/3/31 17:12
@DependencyLibrary：无
@MainFunction：无
@FileDoc： 
    authentication.py
    文件说明
@ChangeHistory:
    datetime action why
    example:
    2021/3/31 17:12 change 'Fix bug'
        
"""
from common.auth.models import UserModel
from sanic_rest_framework.authentication import BaseTokenAuthenticate
from sanic_rest_framework.exceptions import APIException
from sanic_rest_framework.request import SRFRequest
from sanic_rest_framework.status import HttpStatus
from sanic_rest_framework.utils import run_awaitable

from jwt import ExpiredSignatureError
from jwt import decode

class TemporaryTokenAuthenticate(BaseTokenAuthenticate):
    """临时 token 不必检查 role_sign"""
    token_key = 'Temporary-Token'
    
    async def _authenticate(self, request: SRFRequest, token_info: dict, **kwargs):
        user_id = token_info.get('user_id')
        if user_id is None:
            raise APIException(message='登录参数错误', http_status=HttpStatus.HTTP_401_UNAUTHORIZED)
        user = await UserModel.get_or_none(pk=user_id)
        if user is None:
            raise APIException(message='登录参数错误', http_status=HttpStatus.HTTP_401_UNAUTHORIZED)
        if not user.is_active:
            raise APIException(message='当前用户已被禁用', http_status=HttpStatus.HTTP_401_UNAUTHORIZED)
        request.user = user


class GeneralTokenAuthenticate(BaseTokenAuthenticate):
    async def _authenticate(self, request: SRFRequest, token_info: dict, **kwargs):
        user_id = token_info.get('user_id')
        role_id = token_info.get('role_id')
        if user_id is None:
            raise APIException(message='登录参数错误', http_status=HttpStatus.HTTP_401_UNAUTHORIZED)
        if role_id is None:
            raise APIException(message='登录参数错误', http_status=HttpStatus.HTTP_401_UNAUTHORIZED)
        user = await UserModel.get_or_none(pk=user_id, now_role_id=role_id)
        if user is None:
            raise APIException(message='登录参数错误', http_status=HttpStatus.HTTP_401_UNAUTHORIZED)
        if not user.is_active:
            raise APIException(message='当前用户已被禁用', http_status=HttpStatus.HTTP_401_UNAUTHORIZED)
        request.user = user

def verify_auth(exception=APIException(message='未登录，请先登录', http_status=HttpStatus.HTTP_403_FORBIDDEN)):
    def set_fun(func):
        async def call_fun(view, request, *args, **kwargs):
            token_key = 'X-Token'
            token_secret = request.app.config.TOKEN_SECRET
            token = request.headers.get(token_key)
            if token is None:
                raise APIException(message='未登录，请先登录'.format(token_key), http_status=HttpStatus.HTTP_401_UNAUTHORIZED)
            token_secret = request.app.config.TOKEN_SECRET
            try:
                token_info = decode(token, token_secret, algorithms=['HS256'])
            except ExpiredSignatureError:
                raise APIException(message='授权已过期,请重新登录', http_status=HttpStatus.HTTP_401_UNAUTHORIZED)
            user_id = token_info.get('user_id')
            role_id = token_info.get('role_id')
            if user_id is None or user_id is None:
                raise APIException(message='登录参数错误', http_status=HttpStatus.HTTP_401_UNAUTHORIZED)
            user = await UserModel.get_or_none(pk=user_id, now_role_id=role_id)
            if user is None:
                raise APIException(message='登录参数错误', http_status=HttpStatus.HTTP_401_UNAUTHORIZED)
            if not user.is_active:
                raise APIException(message='当前用户已被禁用', http_status=HttpStatus.HTTP_401_UNAUTHORIZED)
            request.user = user
            return await run_awaitable(func,view, request, *args, **kwargs)
        return call_fun
    return set_fun